package com.china.cnlongdb.basic.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.china.cnlongdb.basic.constant.LongDbConstant;

/**
 * 系统名称：FieldHandlerUtils.java
 * 模块名称：
 * 模块描述：对象反射处理类
 * 功能列表：
 * 模块作者：ZOUYONG
 * 开发时间：2018年12月5日 下午9:31:20
 * 模块路径：com.china.cnlongdb.basic.utils.FieldHandlerUtils
 * 更新记录：
 */
public class FieldHandlerUtils {

	/**
	 * 功能描述：将对象转换成longdb-Map对象
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月25日 下午9:26:28
	 * 更新记录：
	 * 返回数据：Map<String,Object>
	 */
	public static Map<String, Object> parserLongObjectToMap(Object object) {
		String longStr = parserObjectLongStr(object);
		return parserLongStrToMap(longStr);
	}
	
	/**
	 * 功能描述：将map对象转换成long数据库的字符串
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月25日 下午9:27:46
	 * 更新记录：
	 * 返回数据：String
	 */
	public static String parserLongMapToStr(Map<String, Object> map) {
		if(null == map || map.size() == 0) {
			return null;
		}
		StringBuffer longStr = new StringBuffer();
		for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
			String key = iter.next();
			Object value = map.get(key);
			longStr.append(LongDbConstant.longdbTableDataTranS)
				.append(key).append(LongDbConstant.longdbTableDataTranI).append(value);
		}
		return longStr.toString();
	}
	
	/**
	 * 功能描述：将longdb - 字符串转换成对象
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月25日 下午9:50:46
	 * 更新记录：
	 * 返回数据：T
	 */
	public static <T> T parserLongStrToObject(String longStr, Class<T> clazz) {
		if(StringUtils.isBlank(longStr)) {
			return null;
		}
		Map<String, Object> map = parserLongStrToMap(longStr);
		return execParserObject(map, clazz);
	}

	/**
	 * 功能描述：转换成对象
	 × 模块作者：ZOUYONG
	 × 开发时间：2018年11月26日 上午11:20:55
	 × 返回数据：T
	 */
	public static <T> T execParserObject(Map<String, Object> map, Class<T> clazz) {
		T object = null;
		try {
			object = clazz.newInstance();
		} catch (Exception e) {
			throw new RuntimeException("数据库结果转换对象异常："+e.getMessage(), e);
		}
		for (; clazz != Object.class; clazz = (Class<T>) clazz.getSuperclass()) { // 向上循环  遍历父类
			Field[] field = clazz.getDeclaredFields();
			for (Field fd : field) {
				Object value = map.get(fd.getName());
				if(null != value) {
					String fieldType = fd.getGenericType().toString();
					// 如果是日期类型
					if(fieldType.equals("class java.util.Date")) {
						value = new Date(Long.valueOf(value.toString()));
						setObjectValue(fd, object, value);
					}
					else if(fieldType.equals("class java.lang.Byte") || fieldType.equals("byte")) {
						setObjectValue(fd, object, Byte.valueOf(value.toString()));
					}
					else if(fieldType.equals("class java.lang.Integer") || fieldType.equals("int")) {
						setObjectValue(fd, object, Integer.valueOf(value.toString()));
					}
					else if(fieldType.equals("class java.lang.Long") || fieldType.equals("long")) {
						setObjectValue(fd, object, Long.valueOf(value.toString()));
					}
					else if(fieldType.equals("class java.lang.Float") || fieldType.equals("float")) {
						setObjectValue(fd, object, Float.valueOf(value.toString()));
					}
					else if(fieldType.equals("class java.lang.Double") || fieldType.equals("double")) {
						setObjectValue(fd, object, Double.valueOf(value.toString()));
					}
					else if(fieldType.indexOf("java.util.List") >= 0) {
						List<Object> list = JSON.parseArray(value.toString(), Object.class);
						setObjectValue(fd, object, list);
					}
					else if(fieldType.indexOf("java.util.Map") >= 0) {
						Map objMap = (Map) JSON.parseObject(value.toString(), Object.class);
						setObjectValue(fd, object, objMap);
					}
					else {
						setObjectValue(fd, object, value);
					}
				}
			}
		}
		return object;
	}

	/**
	 * 功能描述：将对象转换成
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月25日 下午8:57:27
	 * 更新记录：
	 * 返回数据：String
	 */
	public static String parserObjectLongStr(Object object) {
		StringBuffer longStr = new StringBuffer();
		Class<?> clazz = object.getClass();
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) { // 向上循环  遍历父类
			Field[] field = clazz.getDeclaredFields();
			for (Field fd : field) {
				String key = fd.getName();
				try {
					Object obj = getObjectValue(fd, object);
					if(null != obj) {
						Object value = null;
						if(obj instanceof String) {
							value = obj.toString().replaceAll("\"", "\\\\\"");
						}
						else if(obj instanceof Number) {
							value = obj;
						}
						else if(obj instanceof Date) {
							value = ((Date)obj).getTime();
						}
						else {
							value = JSON.toJSONString(obj);
						}
						if(null != value) {
							longStr.append(LongDbConstant.longdbTableDataTranS)
								.append(key).append(LongDbConstant.longdbTableDataTranI).append(value);
						}
					}
				} catch(Exception e) {}
			}
		}
		return longStr.toString();
	}
	
	/**
	 * 功能描述：将字符串转换成Map对象
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月25日 下午9:18:35
	 * 更新记录：
	 * 返回数据：Map<String,Object>
	 */
	public static Map<String, Object> parserLongStrToMap(String longStr) {
		
		if(StringUtils.isBlank(longStr)) {
			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		String[] longArray = LongDbConstant.transPattern.split(longStr);
		for (String attribute : longArray) {
			if(StringUtils.isBlank(attribute)) {
				continue;
			}
			String[] value = LongDbConstant.traniPattern.split(attribute);
			String text = "";
			if(value.length > 1) {
				text = attribute.substring(value[0].length()+LongDbConstant.longdbTableDataTranI.length(), attribute.length());
			}
			map.put(value[0], text);
		}
		return map;
	}
	
	/**
	 * 功能描述：通过反射获取对象的值
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月11日 下午1:12:25
	 * 更新记录：
	 * 返回数据：Object
	 */
	public static Object getObjectValue(Field field, Object obj) {
		Object value = null;
		try {
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
			Method m = pd.getReadMethod(); // 获得读方法
			// 调用getter方法获取属性值 
			value = m.invoke(obj);
		} catch(Exception e) {
			throw new RuntimeException("操作反射读取数据异常["+field.getName()+"]：" + e.getMessage());
		}
		return value;
	}
	
	/**
	 * 功能描述：给属性赋值
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年11月11日 下午1:29:00
	 * 更新记录：
	 * 返回数据：void
	 */
	public static Object setObjectValue(Field field, Object object, Object value) {
		PropertyDescriptor pd = null; Method wM = null;
		try {
			pd = new PropertyDescriptor(field.getName(), object.getClass());
			value = handByFieldType(field, value);
			wM = pd.getWriteMethod(); // 获得写方法
			wM.invoke(object, value);
		} catch (Exception e) {
			String err = "操作反射写入数据异常["+field.getName()+"]：";
			if(null != pd && null != wM) {
				try {
					String classPath = field.getGenericType().toString();
					if(classPath.startsWith("class ")) {
						classPath = classPath.replace("class ", "");
					}
					value = JSON.parseObject(value.toString(), Class.forName(classPath));
					wM.invoke(object, value);
				} catch (Exception et) {
					throw new RuntimeException(err + et.getMessage());
				}
			} else {
				throw new RuntimeException(err + e.getMessage());
			}
		}
		return object;
	}
	
	/**
	 * 功能描述：处理不能转换的特殊类型
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年7月26日 上午9:01:44
	 × 返回数据：Object
	 */
	public static Object handByFieldType(Field field, Object value) {
		if(field.getType().toString().equals("class java.lang.Boolean") || 
				field.getType().toString().equals("boolean")) {
			value = Boolean.valueOf(value.toString());
		}
		return value;
	}

}
